/**
 * Repositories is the class used to manage Repository objects. It can create, edit, or delete a Repository
 * and attach or detach Module to/from this Repository.
 * 
 * @author Eric LEON
 * @version 1.0.0
 */
package controllers;

import javax.persistence.PersistenceException;

import models.Module;
import models.Repository;
import play.Logger;
import play.i18n.Messages;
import play.mvc.With;

@With(Secure.class)
public class Repositories extends RepoController {

	/**
	 *  Create a new empty repository object and render it.
	 */
	public static void create(String m_idx, String r_idx, String t_idx) {
		// Create a new repository object
		Repository rep = new Repository();
		// Generate a generic name
		rep.name = String.format("repository%d", Repository.count() + 1);
		// Save index page layout
		saveLayout(m_idx, r_idx, t_idx);
		// Show repository page
		render("@showRepository", rep);
	}

	/**
	 *  Edit repository identified by the given id.
	 * @param id	The Repository object id.
	 */
	public static void show(String m_idx, String r_idx, String t_idx, Long id) {
		// Retrieve the repository object
		Repository rep = Repository.findById(id);
		// Save index page layout
		saveLayout(m_idx, r_idx, t_idx);
		// Show repository page
		render("@showRepository", rep);
	}
	
	/**
	 *  Delete the repository identified by the given id.
	 * @param id	The Repository object id
	 */
	public static void delete(String m_idx, String r_idx, String t_idx, Long id) {
		// Retrieve the repository object
		Repository rep = Repository.findById(id);
		// Delete it
		rep.delete();
		// Save index page layout
		saveLayout(m_idx, r_idx, t_idx);
		// Display index page
		Application.index();
	}

	/**
	 * Creates a new repository object or edits an existing one.
	 * @param rep
	 * @param id
	 * @param modid
	 */
	public static void save(Repository rep, Long id, Long modid) {

		// Keep index page layout
		keepLayout();
		
		validation.required("rep.name", rep.name);

		Repository old = null;
		Module mod = null;
		
		if (!validation.hasErrors()) {
			if (id == null) {
				// Repository not yet created
				old = null;
				// Repository name must be unique: find it into the database
				if (Repository.count("name", rep.name) > 0) {
					// Repository name already created, generate a validation error 
					validation.addError("rep.name", Messages.get("repository.uniquename"));
				} else if (modid != null) {
					try {
						// Retrieve attached module from database
						mod = Module.findById(modid);
					} catch (Exception e) {
						validation.addError("modid", Messages.get("module.notfound", e.getMessage()));
					}
				}
			} else {
				// Retrieve original repository from database
				old = Repository.findById(id);
				// Test for module rename
				if (!old.name.equals(rep.name)) {
					// It must be unique, see if it already exists into the database
					if (Repository.count("name", rep.name) > 0) {
						// Repository name already created, generate a validation error 
						validation.addError("rep.name", Messages.get("repository.uniquename"));
					}
				}
			}
		}
		
		if (!validation.hasErrors()) {
	    	// No validation error, save the created repository object
	    	try {
	    		if (old != null) {
		    		// Save it into database
					old.edit("rep", params.all());
					old.save();
	    		} else {
		    		// Save it into database
					rep.save();
					if (mod != null) {
						rep.attachModule(mod);
						rep.save();
					}
	    		}
		    	// Display main page
				Application.index();
		        return;
	    	} catch (PersistenceException pe) {
				flash.error(Messages.get("repository.createfailure", pe.getMessage()));
	    	} catch (Exception e) {
				flash.error(Messages.get("repository.createfailure", e.getMessage()));
	    	}
	    }
		
        // Display the same page
		if (id != null) {
	        // Restore module object from database to populate versions collection
	        rep = Repository.findById(id);
		}
	    render("@showRepository", rep);
	}

	/**
	 * Attach module to this repository. The module is added to the repository modules collection.
	 * @param id	the repository identifier
	 * @param modid	the module identifier
	 */
	public static void attachModule(Long id, Long modid) {

		// Keep index page layout
		keepLayout();
		
		validation.required(id);
		validation.required(modid);

		Repository rep = null;
		Module mod = null;
		
		try { 
			rep = Repository.findById(id);
		} catch (Exception e) {
			Logger.error("FindById error %s", e.getMessage());
			validation.addError("id", Messages.get("repository.notfound", e.getMessage()));
		}

		try { 
			mod = Module.findById(modid);
		} catch (Exception e) {
			Logger.error("FindById error %s", e.getMessage());
			validation.addError("modid", Messages.get("module.notfound", e.getMessage()));
		}
		
		if (!validation.hasErrors()) {
			if (rep.getModule(mod.name) != null) {
				Logger.error("Module %s is already attached to repository %s", mod, rep);
				validation.addError("name", Messages.get("repository.alreadyattached"));
			}
		}
		
		if (!validation.hasErrors()) {
	    	// No validation error, save the created repository object
	    	try {
				// Attach module to this repository
				rep.attachModule(mod);
				rep.save();
	    	} catch (PersistenceException pe) {
				flash.error(Messages.get("repository.attachfailure", pe.getMessage()));
	    	} catch (Exception e) {
				flash.error(Messages.get("repository.attachfailure", e.getMessage()));
	    	}
	    }

        // Display the same page
        render("@showRepository", rep);
	}

	/**
	 * Detach module from this repository. The module is removed from the repository modules collection.
	 * @param id	the repository identifier
	 * @param modid	the module identifier
	 */
	public static void detachModule(Long id, Long modid) {

		// Keep index page layout
		keepLayout();
		
		validation.required(id);
		validation.required(modid);

		Repository rep = null;
		Module mod = null;
		
		try { 
			rep = Repository.findById(id);
		} catch (Exception e) {
			Logger.error("FindById error %s", e.getMessage());
			validation.addError("id", Messages.get("repository.notfound", e.getMessage()));
		}

		try { 
			mod = Module.findById(modid);
		} catch (Exception e) {
			Logger.error("FindById error %s", e.getMessage());
			validation.addError("modid", Messages.get("module.notfound", e.getMessage()));
		}
		
		if (!validation.hasErrors()) {
			if (rep.getModule(mod.name) == null) {
				Logger.error("Module %s is not attached to repository %s", mod, rep);
				validation.addError("name", Messages.get("repository.notattached"));
			}
		}
		
		try { 
			rep.detachModule(mod);
			rep.save();
		} catch (Exception e) {
			flash.error("repository.detachfailure", e.getMessage());
		}
		
        // Display the same page
        render("@showRepository", rep);
	}
}
